package cn.xw.mq.producer;

import cn.xw.config.RabbitMQConfig;
import cn.xw.entity.MessageSendDTO;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

/**
 * @author AnHui OuYang
 * @version 1.0
 * created at 2023-04-14 21:39
 * 测试生产者
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class TestProducer {

    //注入rabbitTemplate对象
    private final RabbitTemplate rabbitTemplate;
    //注入StringRedisTemplate对象
    private final StringRedisTemplate redisTemplate;

    /***
     * 生产者方法
     * @param msg 消息
     */
    public void producerSendMsg(MessageSendDTO msg) {
        ValueOperations<String, String> forValue = redisTemplate.opsForValue();
        try {
            //防止重复提交
            //若设置成功则为True，设置不成功或者设置的值已经存在则返回False
            //这里设置20秒代表自动过期，一旦设置这个键值，消息被成功投递则不删除（防止20秒内重复提交），但是投递失败
            //以后我需要删除这个键值，方便下次继续设置投递；；具体按照实际设置过期时间
            Boolean result = forValue.setIfAbsent(msg.getUUID() + "-delivery", String.valueOf(msg.getMsgID()),
                    20, TimeUnit.SECONDS);
            //判断设置成功则发送消息（否则这个消息可能多次发送给消费者）
            if (Boolean.TRUE.equals(result)) {
                //消息转换为JSON格式并转为字节数组
                byte[] bytes = JSONObject.toJSONString(msg).getBytes(StandardCharsets.UTF_8);
                //发送消息
                rabbitTemplate.convertAndSend(RabbitMQConfig.ORDINARY_DIRECT_EXCHANGE, RabbitMQConfig.ROUTE_KEY, bytes);
            } else {
                log.info("消息已经由生产者发送投递了，请忽重复投递！");
            }
        } catch (Exception e) {
            //若生产者投递出现问题则代表投递不成功，删除这次缓存
            redisTemplate.delete(msg.getUUID() + "-delivery");
        }
    }
}
